package com.cobra.json2tree;

import com.cobra.TreeNode;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;

import java.io.File;
import java.util.concurrent.atomic.AtomicInteger;

public class Json2TreeUtil {

    private static ObjectMapper mapper = new ObjectMapper();
    public static TreeNode json2tree(File json,String rootName) throws Exception{
        JsonNode root = mapper.readTree(json);
        return json2tree(root,rootName,null,getValue(root));
    }
    public static TreeNode json2tree(String json,String rootName) throws Exception {
        JsonNode root = mapper.readTree(json);
        return json2tree(root,rootName,null,getValue(root));
    }
    private static String getValue(JsonNode node){
        JsonNodeType nodeType = node.getNodeType();
        switch (nodeType){
            case OBJECT:
            case ARRAY: return nodeType.name();
            default: return node.asText();
       }
    }
    private static TreeNode array2tree(ArrayNode arrayNode,String rootName,Long parentId) throws Exception{
        TreeNode rootNode = new TreeNode(rootName,parentId,JsonNodeType.ARRAY.name(),arrayNode.getNodeType().name());
        AtomicInteger index = new AtomicInteger();
        arrayNode.iterator().forEachRemaining(arrayNodeChild->{
            try {
                rootNode.setChild(json2tree(arrayNodeChild,rootName+"-child-"+index.getAndIncrement(),rootNode.getId(),getValue(arrayNodeChild)));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return rootNode;
    }

    private static TreeNode json2tree(JsonNode root,String rootName,Long parentId,String value) throws Exception {
        if(root.getNodeType().equals(JsonNodeType.ARRAY)){
            return array2tree((ArrayNode)root,rootName,parentId);
        }
        TreeNode rootNode = new TreeNode(rootName,parentId,value,root.getNodeType().name());
        root.fields().forEachRemaining(child->{
            try {
                JsonNode childNode = child.getValue();
                JsonNodeType childNodeType = childNode.getNodeType();
                switch (childNodeType){
                    case ARRAY: rootNode.setChild(array2tree((ArrayNode) childNode,child.getKey(),rootNode.getId()));break;
                    case OBJECT: rootNode.setChild(json2tree(childNode,child.getKey(),rootNode.getId(),getValue(childNode))); break;
                    default: rootNode.setChild(new TreeNode(child.getKey(),rootNode.getId(),getValue(childNode),childNode.getNodeType().name())); break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        return rootNode;
    }
}
